class Datum {
    constructor (props) {
        const {data, value, valueField} = props;
        this.data = data || [];
        this.value = value || [];
        this.valueField = valueField || 'id';

        this.dataMap = new Map();
        this.valueMap = new Map();
        this.events = {};
        this.headerEvent = null;
        this.setData(this.data);
        this.setValue(this.value);
    }

    bind (id, update) {
        this.events[id] = update;
    }

    unbind (id) {
        delete this.events[id];
    }

    bindHeader (update) {
        this.headerEvent = update;
    }

    unbindHeader () {
        this.headerEvent = null;
    }

    setData (data) {
        this.dataMap = new Map();
        this.data = data;
        if (!data) { return; }
        this.initData(data);
        this.initValue();
    }

    setValue (value) {
        this.value = value;
        if (value && value !== this.cachedValue) {
            this.initValue();
        }
    }

    getValue () {
        const value = [];
        this.valueMap.forEach((checked, id) => {
            if (checked === 1) {
                value.push(id);
            }
        });
        this.cachedValue = value;
        return value;
    }

    initData (data) {
        data.forEach(item => {
            this.dataMap.set(item[this.valueField], item);
        });
    }

    initValue () {
        if (!this.data || !this.value) { return undefined; }
        this.value.forEach(id => {
            this.setValueMap(id, true);
        });
        if (this.headerEvent) {
            this.headerEvent();
        }
    }

    setValueMap (id, checked) {
        if (checked) {
            this.valueMap.set(id, checked);
        } else {
            this.valueMap.delete(id);
        }
        const update = this.events[id];
        if (update) {
            update();
        }
    }

    getChecked (id) {
        const value = this.get(id);
        let checked = value === 1;
        if (value === 2) { checked = 'indeterminate'; }
        return checked;
    }

    getHeaderChecked () {
        let checkAll = 0;
        if (this.data.length !== 0) {
            const keyLength = this.valueMap.size;
            if (keyLength === this.data.length) {
                checkAll = 1;
            } else if (keyLength === 0) {
                checkAll = 0;
            } else {
                checkAll = 'indeterminate';
            }
        }
        return checkAll;
    }

    get (id) {
        return this.valueMap.get(id);
    }

    set (id, checked) {
        if (!this.isDisabled(id)) { this.setValueMap(id, checked); }
        if (this.headerEvent) {
            this.headerEvent();
        }
    }

    setHeader (checked) {
        console.log(checked);
        if (checked) {
            for (const id of this.dataMap.keys()) {
                if (!this.valueMap.has(id)) {
                    this.setValueMap(id, 1);
                }
            }
            if (this.headerEvent) {
                this.headerEvent();
            }
        } else {
            for (const id of this.dataMap.keys()) {
                if (this.valueMap.has(id)) {
                    this.valueMap.delete(id);
                    const update = this.events[id];
                    if (update) {
                        update();
                    }
                }
            }
            if (this.headerEvent) {
                this.headerEvent();
            }
        }
    }

    isDisabled (id) {
        const node = this.dataMap.get(id);
        if (node) { return node.disabled; }
        return false;
    }
}

export default Datum;
